#include "BarkerPair.h"

#include <algorithm>
#include <cmath>
#include <iterator>
#include <vector>
std::ostream& operator<<(std::ostream& cout, const BarkerPair& val) {
    cout << "x:[";
    for (int i = 0; i < (val.len - 1); i++) {
        cout << val.x[i] << ", ";
    }
    cout << val.x[val.len - 1] << "], y:[";
    for (int i = 0; i < (val.len - 1); i++) {
        cout << val.y[i] << ", ";
    }
    cout << val.y[val.len - 1] << "], len:" << val.len << ", auto:[";
    for (int i = 0; i < (val.len - 1); i++) {
        cout << val.autocorrelation[i] << ", ";
    }
    cout << val.autocorrelation[val.len - 1] << "], peak:" << val.peak
         << ", isValid:" << val.isValid;
    return cout;
}

bool isBarkerPair(const std::vector<int>& autocorrelation) {
    if (-1 <= autocorrelation[0] && autocorrelation[0] <= 1)
        return false;  // 主峰要大
    for (int i = 1; i < autocorrelation.size(); ++i) {
        // 副峰要小
        if (autocorrelation[i] < -1 || autocorrelation[i] > 1) return false;
    }
    return true;
}

std::vector<int> getAutocorrelation(const std::vector<int>& x,
                                    const std::vector<int>& y) {
    int n = x.size();
    std::vector<int> autocorrelation;
    for (int shift = 0; shift < n; ++shift) {
        int sum = 0;
        for (int i = 0; i < n - shift; ++i) {
            sum += x[i] * y[i + shift];
        }
        autocorrelation.push_back(sum);
    }
    return autocorrelation;
}

std::vector<int> runLengthToSequence(const std::vector<int>& runLength) {
    std::vector<int> sequence;
    for (int i = 0; i < runLength.size(); ++i) {
        for (int j = 0; j < runLength[i]; ++j) {
            // 始终认为游程序列是从1的游程开始的，如果是-1开始，则游程对应为0
            sequence.push_back(i % 2 == 0 ? 1 : -1);
        }
    }
    return sequence;
}

std::vector<int> sequenceToRunLength(const std::vector<int>& sequence) {
    std::vector<int> runLength;
    int cnt = 1;
    for (int i = 1; i < sequence.size(); ++i) {
        if (sequence[i] == sequence[i - 1]) {
            cnt += 1;
        } else {
            runLength.push_back(cnt);
            cnt = 1;
        }
    }
    runLength.push_back(cnt);
    if (sequence[0] != 1) {
        // 始终认为游程序列是从1的游程开始的，如果是-1开始，则游程对应为0
        runLength.insert(runLength.begin(), 0);
    }
    return runLength;
}

BarkerPair::BarkerPair(const std::vector<int>& x, const std::vector<int>& y) {
    this->x = x;
    this->y = y;

    this->len = this->x.size();
    this->autocorrelation = getAutocorrelation(this->x, this->y);
    this->isValid = isBarkerPair(this->autocorrelation);
    if (this->isValid)
        this->peak = std::abs(this->autocorrelation[0]);
    else
        this->peak = 0;
}

bool BarkerPair::operator<(const BarkerPair& other) const {
    if (this->isValid == other.isValid) {
        return std::abs(this->peak) > std::abs(other.peak);
    }
    if (this->isValid && !other.isValid) {
        return true;
    }
    if (!this->isValid && other.isValid) {
        return false;
    }
    return false;
}
